﻿using System;
using System.Collections.Generic;
using System.Linq;
//using System.Windows.Forms;
using System.IO;
using System.Xml;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace FEClone
{
    /*static class Classes
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
    */
    public enum ePossibleWeaponRanks { D, C, B, A, S, SS };

    [Serializable]
    public class Chapter
    {
        Map ChapterMap;
        public List<Character> UsableCharacters;

    }

    [Serializable]
    public class Script
    {

    }

    [Serializable]
    public class Character
    {
        public string sName;
        public int iMaxHP;
        public int iHP;
        public int[] aLvl;
        public int iStr;
        public int iDef;
        public int iSkl;
        public int iSpd;
        public int iLck;
        public int iMag;
        public int iRes;
        public int iCharacterRef;
        public Weapon weaponequipped;
        public enum ePossibleTypes { Foot, Horse, Armoured, Pegasus, Wyvren };
        public int iType;
        public int iMove;
        //private items[] inventory;
        //private string class;

        //TODO
        //Add supports, etc.

        public Character()
        {
            aLvl = new int[1];
        }

        public void LoadCharacterFromCSVFile(string myPath, int iMyRef)
        {

            //TODO
            //Check for invalid character ref, path
            CSVFile myFile = new CSVFile(myPath);
            List<Dictionary<string, string>> diclistCharacters = new List<Dictionary<string, string>>();
            diclistCharacters = myFile.makedictionaries();
            Dictionary<string, string> dicMe = new Dictionary<string, string>();
            dicMe = diclistCharacters[iMyRef];

            sName = dicMe["name"];
            aLvl[0] = Convert.ToInt32(dicMe["lvl"]);
            aLvl[1] = Convert.ToInt32(dicMe["exp"]);
            iStr = Convert.ToInt32(dicMe["str"]);
            iDef = Convert.ToInt32(dicMe["def"]);
            iSkl = Convert.ToInt32(dicMe["skl"]);
            iSpd = Convert.ToInt32(dicMe["spd"]);
            iLck = Convert.ToInt32(dicMe["lck"]);
            iMag = Convert.ToInt32(dicMe["mag"]);
            iRes = Convert.ToInt32(dicMe["Res"]);
            iCharacterRef = iMyRef;

        }



    }

    class BattleEngine
    {

        Character AttackingCharacter = new Character();
        Character DefendingCharacter = new Character();

        int calcattackspeed()
        {
            int attackspeed = (AttackingCharacter.iSpd - (AttackingCharacter.weaponequipped.iWt - AttackingCharacter.iStr));

            if (attackspeed < 0) attackspeed = 0;

            return attackspeed;
        }

        int calcdamage()
        {
            bool IsMagical = checkifattackmagical();

            int iattackstrength;
            int iTriangeBonus = calctrianglebonus();
            int iEffectiveCoefficient = calceffectivecoefficient();

            if (IsMagical == true)
            {
                iattackstrength = AttackingCharacter.iMag;

            }
            else
            {

                iattackstrength = AttackingCharacter.iStr;

            }

            int possibledamage = iattackstrength + ((AttackingCharacter.weaponequipped.iMt + iTriangeBonus) * iEffectiveCoefficient);
            //TODO: Add support bonus, height bonus

            return possibledamage - calcdefence();
        }

        int calceffectivecoefficient()
        {
            if (AttackingCharacter.weaponequipped.aStrongAgainst[DefendingCharacter.iType] == 1)
            {
                return 3;

            }
            else return 1;
        }

        int calctrianglebonus()
        {
            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Sword)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Axe)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Lance)
                {
                    return -1;
                }
            }
            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Axe)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Lance)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Sword)
                {
                    return -1;
                }
            }
            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Lance)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Sword)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Axe)
                {
                    return -1;
                }
            }
            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Fire)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Wind)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Thunder)
                {
                    return -1;
                }
            }
            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Wind)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Thunder)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Fire)
                {
                    return -1;
                }
            }
            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Thunder)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Fire)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Wind)
                {
                    return -1;
                }
            }

            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Thunder
                | AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Fire
                | AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Wind)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Light)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Dark)
                {
                    return -1;
                }
            }

            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Dark)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Thunder
                | DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Fire
                | DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Wind)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Light)
                {
                    return -1;
                }
            }

            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Light)
            {
                if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Dark)
                {
                    return 1;
                }
                else if (DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Thunder
                | DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Fire
                | DefendingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Wind)
                {
                    return -1;
                }
            }


            return 0;
        }

        int calcdefence()
        {
            bool IsMagical = checkifattackmagical();

            if (IsMagical == true)
            {
                return DefendingCharacter.iDef;
            }
            else return DefendingCharacter.iRes;

            //TODO add buddy support bonus, height bonus, terrain bonus
        }

        int calcaccuracy()
        {
            int possibleaccuracy = AttackingCharacter.weaponequipped.iHit + (AttackingCharacter.iStr * 2) + AttackingCharacter.iLck + (calctrianglebonus() * 10);

            return possibleaccuracy - calcavoid();
        }

        int calcavoid()
        {
            return (calcattackspeed() * 2) + DefendingCharacter.iLck;
        }

        bool checkifattackmagical()
        {
            if (AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Thunder
               | AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Fire
               | AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Wind
               | AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Dark
               | AttackingCharacter.weaponequipped.iWeaponSubtype == (int)Weapon.ePossibleWeaponSubTypes.Light)
            {
                return true;
            }
            else return false;

        }

        int DefendingCharacterHPAfterAttack()
        {
            Random r = new Random();
            r.Next(100);
            if (Convert.ToInt32(r) > calcaccuracy())
            {
                return DefendingCharacter.iHP;
            }

            return DefendingCharacter.iHP - calcdamage();

        }
    }

    [Serializable]
    public class Item
    {
        public string sName;
        public string sDescription;
        public enum ePossibleItemTypes { Weapon, Healing, StatBoost, Misc };
        public int iItemType;
        public int iItemRef;
    }

    [Serializable]
    public class Weapon : Item
    {
        public enum ePossibleWeaponSubTypes { Sword, Lance, Axe, Knife, Strike, Fire, Thunder, Wind, Light, Dark };
        public int iWeaponSubtype;
        public int iWt;
        public int iMt;
        public int iHit;
        public int iCrt;
        public int[] aUses;
        public int iWEx;
        public int iWorth;
        public int[] aStrongAgainst;

        public Weapon()
        {
            iItemType = (int)ePossibleItemTypes.Weapon;
            aUses = new int[1];
            int maxValue = Enum.GetValues(typeof(Character.ePossibleTypes)).Cast<int>().Max();
            aStrongAgainst = new int[maxValue];
        }

    }

    class Staff : Weapon
    {

    }

    class CSVFile
    {

        private string filepath;
        private List<string[]> parsedfile;

        public CSVFile(string path)
        {
            filepath = path;
            parsedfile = new List<string[]>();
            parsedfile = simpleparseCSV();

        }

        public List<string[]> simpleparseCSV()
        {
            List<string[]> parsedData = new List<string[]>();

            try
            {
                using (StreamReader readFile = new StreamReader(filepath))
                {
                    string line;
                    string[] row;

                    while ((line = readFile.ReadLine()) != null)
                    {
                        row = line.Split(',');
                        parsedData.Add(row);
                    }
                }
            }
            catch (Exception e)
            {
                //MessageBox.Show(e.Message);
            }

            return parsedData;
        }

        public List<Dictionary<string, string>> makedictionaries()
        {

            List<Dictionary<string, string>> DictionaryList = new List<Dictionary<string, string>>();

            string[] headerrow = new string[parsedfile[0].Length];
            parsedfile[0].CopyTo(headerrow, 0);

            for (int j = 1; j < (parsedfile.Count); j++)
            {

                Dictionary<string, string> myDictionary = new Dictionary<string, string>();

                string[] currentrow = new string[headerrow.Length];
                parsedfile[j].CopyTo(currentrow, 0);

                for (int i = 0; i < (headerrow.Length - 1); i++)
                {
                    myDictionary.Add(headerrow[i], currentrow[i]);
                }

                DictionaryList.Add(myDictionary);
            }

            return DictionaryList;
        }
    }
    class XMLFile
    {

        public void XMLSerialize(Character c)
        {

            //The Xml.Serialization namespace contains an XmlSerializer class that serializes an object to XML. 
            //When you create an instance of XmlSerializer, you pass the type of the class that you want to serialize into its constructor
            string characterfilename = "Character-" + Convert.ToString(c.iCharacterRef) + "-" + c.sName;

            if (characterfilename.Contains("base"))
            {
                throw new InvalidOperationException("Overwriting of base files not allowed");
            }

            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(c.GetType());
            System.Xml.XmlWriter xmlwriter = System.Xml.XmlWriter.Create(characterfilename);
            x.Serialize(xmlwriter, c);
            xmlwriter.Close();

        }
        public void XMLSerialize(Weapon w)
        {

            //The Xml.Serialization namespace contains an XmlSerializer class that serializes an object to XML. 
            //When you create an instance of XmlSerializer, you pass the type of the class that you want to serialize into its constructor
            string weaponfilename = "Weapon-" + Convert.ToString(w.iItemRef) + "-" + w.sName;

            if (weaponfilename.Contains("base"))
            {
                throw new InvalidOperationException("Overwriting of base files not allowed");
            }

            try
            {
                System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(w.GetType());
                System.Xml.XmlWriter xmlwriter = System.Xml.XmlWriter.Create(weaponfilename);
                x.Serialize(xmlwriter, w);
                xmlwriter.Close();
            }
            catch (Exception e)
            {
                string s = e.ToString();

                Console.WriteLine(s);

            }


        }

        public Character XMLDeserialize(Character c)
        {
            string characterfilename = "Character-" + Convert.ToString(c.iCharacterRef) + "-" + c.sName;
            Character newc = null;


            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(c.GetType());
            System.Xml.XmlReader xmlreader = System.Xml.XmlReader.Create(characterfilename);
            newc = (Character)x.Deserialize(xmlreader);
            xmlreader.Close();

            return newc;

        }

        public Weapon XMLDeserialize(Weapon w)
        {
            string weaponfilename = "Weapon-" + Convert.ToString(w.iItemRef) + "-" + w.sName;
            Weapon neww = null;


            System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(w.GetType());
            System.Xml.XmlReader xmlreader = System.Xml.XmlReader.Create(weaponfilename);
            neww = (Weapon)x.Deserialize(xmlreader);
            xmlreader.Close();

            return neww;

        }

    }

}
